package com.zengyan.gd.service.impl;

import com.zengyan.gd.core.ServiceException;
import com.zengyan.gd.enums.Sex;
import com.zengyan.gd.form.GetUserForm;
import com.zengyan.gd.form.UserLoginForm;
import com.zengyan.gd.model.Event;
import com.zengyan.gd.model.Organization;
import com.zengyan.gd.model.Relationship;
import com.zengyan.gd.model.SignUp;
import com.zengyan.gd.model.StudentInfo;
import com.zengyan.gd.model.User;
import com.zengyan.gd.model.resultModel.EventResultModel;
import com.zengyan.gd.repository.EventRespository;
import com.zengyan.gd.repository.OU_Respository;
import com.zengyan.gd.repository.OrganizationRepository;
import com.zengyan.gd.repository.SignUpRespository;
import com.zengyan.gd.repository.UserRepository;
import com.zengyan.gd.service.OrganizationService;
import com.zengyan.gd.service.UserService;
import com.zengyan.gd.utils.ImageType;
import com.zengyan.gd.utils.ImageUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private UserRepository mUserRepository;

    @Autowired
    private OU_Respository mOURespoitory;

    @Autowired
    private SignUpRespository mSignUpRespository;

    @Autowired
    private EventRespository mEventRespository;

    @Autowired
    private OrganizationService mOrgService;

    @Autowired
    private OrganizationRepository mOrgRespoitory;
    @Override
    public User login(UserLoginForm loginForm) throws Exception {
        MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();
        paramMap.add("JWC_API_KEY", "weacsoft");
        paramMap.add("number", loginForm.getStudentNum());
        paramMap.add("password", loginForm.getPassword());
        String url = "http://jwcwx.gcu.edu.cn/api/user/login";

        restTemplate.setErrorHandler(new ResponseErrorHandler() {
            @Override
            public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
                switch (clientHttpResponse.getStatusCode().value()) {
                    case 401:
                        throw new ServiceException("查询无此学号");
                    case 402:
                        throw new ServiceException("密码错误");
                }
                return false;

            }

            @Override
            public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
            }
        });

        StudentInfo studentInfo;
        User user;
        studentInfo = restTemplate.postForObject(url, paramMap, StudentInfo.class);
        if (studentInfo == null) throw new ServiceException("登陆失败");
        switch (studentInfo.getCode()) {
            case "401":
                throw new ServiceException("查询无此学号");
            case "402":
                throw new ServiceException("密码错误");
        }
        user = mUserRepository.findByStudentNum(studentInfo.getData().getXh());
        if (user != null) return user;


        user = new User();
        user.setName(studentInfo.getData().getXm());
        user.setStudentNum(studentInfo.getData().getXh());
        user.setCollege(studentInfo.getData().getXy());
        user.setProfession(studentInfo.getData().getZymc());
        user.setClazz(studentInfo.getData().getXzb());
        user.setGrade(studentInfo.getData().getDqszj());
        user.setSex(studentInfo.getData().getXb().equals("男") ? Sex.MAN : Sex.WOPMAN);
        return mUserRepository.save(user);
    }

    @Override
    public List<Organization> getAllOrg_I_Join(String stuNum) throws Exception{

        List<Relationship> relationships = mOURespoitory.findByStudentNum(stuNum);

        List<Organization> organizations = new ArrayList<>();
        for (Relationship relationship : relationships) {
            organizations.add(mOrgRespoitory.getOne(relationship.getOrgId()));
        }

        return organizations;
    }

    @Override
    public User updateImage(String stuNum, MultipartFile file, ImageType type) throws Exception {

        String url = ImageUtils.saveUserImage(file, type, stuNum);
        User user = mUserRepository.findByStudentNum(stuNum);
        switch (type) {
            case userAvatar:
                user.setAvatarUrl(url);
                break;
            case userBg:
                user.setBgUrl(url);
                break;
        }
        mUserRepository.save(user);
        return user;
    }

    @Override
    public User getUser(String stuNum) throws Exception {
        User user = mUserRepository.findByStudentNum(stuNum);
        if (user == null) throw new ServiceException("该用户不存在");
        return user;
    }

    @Override
    public List<User> searchPeople(String stunum, String message) throws Exception {
        List<User> userList = new ArrayList<>();
        List<Relationship> relationships = mOURespoitory.findByStudentNum(stunum);

        for (Relationship relationship : relationships) {
            GetUserForm getUserForm = mOrgService.getMyUsers(relationship.getOrgId());
            List<User> orgUsers = getUserForm.getUsers();
            for (User user : orgUsers) {
                if (user.getName().contains(message.trim())) {
                    if (!isInList(user, userList)) {
                        userList.add(user);
                    }
                }
            }
        }
        return userList;
    }

    @Override
    public SignUp signUpInEvent(SignUp signUp) throws Exception {
        return mSignUpRespository.save(signUp);
    }

    @Override
    public List<Event> getEventIjoin(String stunum) {
        List<SignUp> signUps = mSignUpRespository.findByStuNum(stunum);
        List<Event> events = new ArrayList<>();
        for (SignUp signUp : signUps) {
            events.add(mEventRespository.getOne(signUp.getEventId()));
        }
        return events;
    }

    @Override
    public List<EventResultModel> getAllEvent(String stunum) throws Exception {
        List<Event> events = mEventRespository.findAll();
        List<SignUp> signUps = mSignUpRespository.findByStuNum(stunum);
        List<EventResultModel> eventResultModels = new ArrayList<>();

        Observable.fromIterable(events)
                .map(event -> {
                    EventResultModel eventResultModel = new EventResultModel();
                    eventResultModel.setEvent(event);
                    for (SignUp signUp : signUps) {
                        if (signUp.getEventId() == event.getId()) {
                            eventResultModel.setSignUp(true);
                        }
                    }
                    return eventResultModel;
                }).subscribe(eventResultModel -> {
            eventResultModels.add(eventResultModel);
        });

        return eventResultModels;
    }

    private boolean isInList(User user, List<User> list) {
        for (User inUser : list) {
            if (inUser.getStudentNum().equals(user.getStudentNum())) {
                return true;
            }
        }
        return false;
    }


}
